//
//  ViewController.m
//  Multithreading
//
//  Created by Charles on 16/2/1.
//  Copyright © 2016年 Charles. All rights reserved.
//

#import "ViewController.h"
@interface ViewController ()

@end

@implementation ViewController

/**
 *  创建视图
 */
- (void)createUI{
    UIButton * button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(0, 0, 100, 20);
    [button setTitle:@"click" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
    button.center = self.view.center;
    [self.view addSubview:button];
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    //    [self createUI];
    //    [self blockOperation];
    //    [self invocationOperation];
    //    [self operationQueue];
    //    [self operationAddDependency];
    [self threadSynchronization];
}

/**
 *  队列组
 */
- (void)buttonClick{
    //创建队列组
    dispatch_group_t group = dispatch_group_create();
    //创建队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //多次使用队列组的方法执行任务,只有异步方法
    //执行3次循环
    dispatch_group_async(group, queue, ^{
        for (NSInteger i = 0; i<3; i++) {
            NSLog(@"group-01-%@",[NSThread currentThread]);
        }
    });
    //主队列执行8次循环
    dispatch_group_async(group, dispatch_get_main_queue(), ^{
        for (NSInteger i = 0; i<8; i++) {
            NSLog(@"group-02-%@",[NSThread currentThread]);
        }
    });
    //执行5次循环
    dispatch_group_async(group, queue, ^{
        for (NSInteger i = 0; i<5; i++) {
            NSLog(@"group-03-%@",[NSThread currentThread]);
        }
    });
    //都完成后会自动通知
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"完成 - %@",[NSThread currentThread]);
    });
    
}
/**
 *  创建一个 Operation 后，需要调用 start 方法来启动任务，它会 默认在当前队列同步执行。当然你也可以在中途取消一个任务，只需要调用其 cancel 方法即可.
 */
- (void)blockOperation{
    NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"BlockOperation");
    }];
    /**
     *  NSBlockOperation 有一个方法：addExecutionBlock: ，通过这个方法可以给 Operation 添加多个执行 Block。这样 Operation 中的任务 会并发执行，它会 在主线程和其它的多个线程 执行这些任务.
     *
     */
    //添加多个Block
    for (NSInteger i = 0; i < 5; i++) {
        [operation addExecutionBlock:^{
            NSLog(@"BlockOperation 第%ld次：%@", i, [NSThread currentThread]);
        }];
    }
    //2.开始任务
    [operation start];
}
/**
 *  NSInvocationOperation
 */
- (void)invocationOperation{
    NSInvocationOperation * operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(start) object:nil];
    [operation start];
}
- (void)start{
    NSLog(@"NSInvocationOperation");
}


/**
 *  队列
 */

- (void)operationQueue{
    //主队列
    //    NSOperationQueue * queue = [NSOperationQueue mainQueue];
    //其他队列
    NSOperationQueue * otherQueue = [[NSOperationQueue alloc]init];
    otherQueue.maxConcurrentOperationCount = 1;
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@", [NSThread currentThread]);
    }];
    //3.添加多个Block
    for (NSInteger i = 0; i < 5; i++) {
        [operation addExecutionBlock:^{
            NSLog(@"OperationQueue 第%ld次：%@", i, [NSThread currentThread]);
        }];
    }
    [otherQueue addOperation:operation];
}
/**
 *  不能添加相互依赖，会死锁，比如 A依赖B，B依赖A。
 */
- (void)operationAddDependency{
    //1.任务一：下载图片
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片 - %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //2.任务二：打水印
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"打水印   - %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //3.任务三：上传图片
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"上传图片 - %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0];
    }];
    //设置依赖
    [operation2 addDependency:operation1];
    [operation3 addDependency:operation2];
    NSOperationQueue * queue = [[NSOperationQueue alloc]init];
    [queue addOperations:@[operation1,operation2,operation3] waitUntilFinished:NO];
}

/**
 *  同步执行 ：我们可以使用多线程的知识，把多个线程都要执行此段代码添加到同一个串行队列，这样就实现了线程同步的概念。
 */
- (void)threadSynchronization{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    __block NSInteger lastTicket = 20;
    dispatch_sync(queue, ^{
        for (NSInteger i = 0; i<22; i++) {
            NSInteger ticket = lastTicket;
            [NSThread sleepForTimeInterval:0.1];
            ticket -= 1;
            lastTicket = ticket;
            NSLog(@"ticket %ld - %@",ticket, [NSThread currentThread]);
            NSLog(@"last ticket %ld - %@",lastTicket, [NSThread currentThread]);
        }
    });
    //NSOperation & NSOperationQueue
    //重点：1. 全局的 NSOperationQueue, 所有的操作添加到同一个queue中
    //     2. 设置 queue 的 maxConcurrentOperationCount 为 1
    //     3. 如果后续操作需要Block中的结果，就需要调用每个操作的waitUntilFinished，阻塞当前线程，一直等到当前操作完成，才允许执行后面的。waitUntilFinished 要在添加到队列之后！
    NSOperationQueue * operationQueue = [[NSOperationQueue alloc]init];
    NSBlockOperation*operation = [NSBlockOperation blockOperationWithBlock:^{
        NSInteger ticket = lastTicket;
        [NSThread sleepForTimeInterval:0.1];
        ticket -= 1;
        lastTicket = ticket;
    }];
    [operationQueue addOperation:operation];
    [operation waitUntilFinished];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
